package mutation;

import java.util.Map;
import java.util.List;
import java.util.LinkedList;
import java.util.HashSet;
import java.util.Set;

import util.GAOperationsConfig;
import util.Randomness;
import instrumentation.Constant;
import instrumentation.ConstantString;
import instrumentation.Data;
import instrumentation.Value;
import instrumentation.ValueArray;
import instrumentation.Virtualinvoke;
import instrumentation.TrackerCoverage;
import ga.GAInfo;
public class MutationFactory {
	public static Mutation getMutationOperator(){
		int ran = Randomness.random.nextInt(90);
		if (ran <= 29) 
			return GAOperationsConfig.getMutationChangeValueStrategy();
		if (ran <= 59) 
			return GAOperationsConfig.getMutationMethodInsertStrategy();
		
		return GAOperationsConfig.getMutationMethodDeleteStrategy();
	}
	public static int getTargetToCover(GAInfo gaInfo){
//		RecommendGenerator recommendGenerator=gaInfo.getRecommendGenerator();
		//Set<Integer> branchClz=recommendGenerator.getAllBranchesClz();
		TrackerCoverage  tracker=gaInfo.getTracker();
		Class<?> cut=gaInfo.getClzToTest();
		Set<Integer> notCoveredBranches=new HashSet<Integer>(gaInfo.getClazzBranches(cut.getName()));
		for(Integer br:	tracker.branchCoveredByIndividual.keySet())
			if(notCoveredBranches.contains(br))
				notCoveredBranches.remove(br);
		List<Integer> value=new LinkedList<Integer>(notCoveredBranches);
		Integer trgtBR=value.get(Randomness.random.nextInt(value.size()));
		return trgtBR;
	}
	public static int getHitTargetToCover(GAInfo gaInfo){
		TrackerCoverage  tracker=gaInfo.getTracker();
		Class<?> cut=gaInfo.getClzToTest();
		
		if(tracker.branchNotCoveredByIndividual.size()==0){
			//System.err.println("MutationFactory.getHitTargetToCover tracker.branchNotCoveredByIndividual.size()==0");
			int trgtbr=getTargetToCover( gaInfo);
	//		System.err.println("MutationFactory.getHitTargetToCover tracker.branchNotCoveredByIndividual.size()==0"+ trgtbr);
			return trgtbr;
		}
		Set<Integer> notCoveredBranches=new HashSet<Integer>(tracker.branchNotCoveredByIndividual.keySet());
		Set<Integer> cutBranches=new HashSet<Integer>(gaInfo.getClazzBranches(cut.getName()));
		for(Integer br:	tracker.branchNotCoveredByIndividual.keySet())
			if(!cutBranches.contains(br))
				notCoveredBranches.remove(br);
		if(notCoveredBranches.size()==0) 
			return getTargetToCover( gaInfo);
		List<Integer> value=new LinkedList<Integer>(notCoveredBranches);
		Integer trgtBR=value.get(Randomness.random.nextInt(value.size()));
		return trgtBR;
	}

	public static List<Value> get_V1_and_V2(Map<Integer, Value> predicates){
		List<Value> values=new LinkedList<Value>();
		Value v1=predicates.get(1);

		Value v2=predicates.get(2);
		if(!(v2 instanceof Constant||v2 instanceof ConstantString))
			v2=null;
		int count=0;
		while(true){
			count++;
			if(v1 instanceof Data||v2 instanceof ConstantString){
				 break;
			}else if(v1 instanceof Virtualinvoke ){
				if((((Virtualinvoke) v1).getD().getType().equals("java.lang.String")))
				if(((Virtualinvoke) v1).getArgs().size()!=0 &&v2==null)
						v2=((Virtualinvoke) v1).getArgs().get(0);
				Data d=((Virtualinvoke) v1).getD();
				if(!(d.isField()||d.isParam())){
					if(((Virtualinvoke) v1).getArgs().size()!=0 )
						v1=((Virtualinvoke) v1).getArgs().get(0);
				}else
					v1=d;
				
			}else if(v1 instanceof ValueArray ){
				if(((ValueArray) v1).getArgs()!=null&&v2==null)
						v2=((ValueArray) v1).getArgs();
				v1=((ValueArray) v1).getD();						
			}
			if(count==100)
				System.out.println("MutationFactory.get_V1_and_V2");
		}
		values.add(v1);
		values.add(v2);
		
		return values;
	}
	public static Object getTpeValue(Value v){
		Object valuetpe=null;
		if(v instanceof Data){
			Data d=(Data) v;
			if(d.isField()){
				valuetpe=d.getType();
			}
			else if(d.getIndxParam()!=-1){
				valuetpe=d.getType();
			}
		}
		return valuetpe;
	}

}
